#pragma once
#include "vertex_description.h"
#include "vertex_uv.h"

#include "vector3.h"

namespace krryn{
namespace scene{
	class vertex_no_position{
	public:
		static const bool m_Available = false;
		static const size_t m_Stride = 0;
		static const size_t m_Size = 0;
	};

	template
	<
		typename _Parent,
		typename _Position = math::vector3f, 
		size_t _Size = 3
	>
	class vertex_position{
	public:
		static const bool m_Available = true;
		static const size_t m_Stride = sizeof(_Position);
		static const size_t m_Size = _Size;

		_Position &get_position(){
			return m_Position;
		}

		const _Position &get_position() const{
			return m_Position;
		}

		_Parent &position(const _Position &a_Position){
			m_Position = a_Position;
			return static_cast<_Parent&>(*this);
		}

	private:
		_Position m_Position;
	};

	class vertex_no_color{
	public:
		static const bool m_Available = false;
		static const size_t m_Stride = 0;
	};

	template
	<
		typename _Parent,
		typename _Color = math::color3, 
		size_t _Size = 3
	>
	class vertex_color{
	public:
		static const bool m_Available = true;
		static const size_t m_Stride = sizeof(_Color);
		static const size_t m_Size = _Size;

		_Color &get_color(){
			return m_Color;
		}

		const _Color &get_color() const{
			return m_Color;
		}

		_Parent &color(const _Color &a_Color){
			m_Color = a_Color;
			return static_cast<_Parent&>(*this);
		}
	private:
		_Color m_Color;
	};

	class vertex_no_normal{
	public:
		static const bool m_Available = false;
		static const size_t m_Stride = 0;
	};

	template
	<
		typename _Parent,
		typename _Normal = math::normal3f
	>
	class vertex_normal{
	public:
		static const bool m_Available = true;
		static const size_t m_Stride = sizeof(_Normal);

		_Normal &get_normal(){
			return m_Normal;
		}

		const _Normal &get_normal() const{
			return m_Normal;
		}

		_Parent &normal(const _Normal &a_Normal){
			m_Normal = a_Normal;
			return static_cast<_Parent&>(*this);
		}
	private:
		_Normal m_Normal;
	};

	template
	<
		typename _Position,
		typename _Color,
		typename _Normal,
		typename _UV
	>
	class basic_vertex
		: public _Position, 
		  public _Color, 
		  public _Normal, 
		  public _UV
	{
	public:
		typedef vertex_description
			<
				_Position, 
				_Color, 
				_Normal, 
				_UV,
				basic_vertex
			> description_type;
	};

	class vertex : public basic_vertex
	<
		vertex_position<vertex>,
		vertex_color<vertex>,
		vertex_no_normal,
		vertex_no_uv
		//vertex_normal<vertex>,
		//vertex_uv<vertex, 2>
	>
	{
	public:
		vertex() {}

		vertex(float a_X, float a_Y, float a_Z) {
			position(math::vector3f(a_X, a_Y, a_Z));
		}
	};
}
}